Syncovery中的PascalScrip


Syncovery 8添加了PascalScript语言,允许您以多种方式自定义配置文件的行为。
请注意,自Syncovery 8发布候选版以来,许多功能的语法已发生变化。 任何名为Profile的参数都已删除。

要更改特定行为,您需要编写一个拦截函数并编写一些代码。 在大多数情况下,当我们收到最好使用自定义脚本实现的功能请求时,我们的技术支持将为您编写代码。但是,我们将尝试完整记录可用的拦截和功能,以便您可以自己进行实验。

通过作业设置类别选项卡上的“Pascal脚本...”复选标记在配置文件中指定脚本。

有用的即用型脚本

可以按原样使用以下脚本,只需将脚本粘贴到PascalScript对话框中即可。

可用的PascalScript拦截

目前提供以下拦截。 将根据需要添加额外的拦截以满足客户的要求。
  • OnDownloadComplete
  • OnGetCustomHeaders
  • OnGetProfilePathBeforeListing
  • OnGetProfilePathBeforeCopying
  • OnHttpPost
  • OnIncludeItem
  • OnProfileResults
  • OnMoveFileToDeletedFolder
  • OnReplaceFilenameLeftToRight
  • OnReplaceFilenameRightToLeft
  • OnScanFolder
  • OnSendEmail
  • OnUploadComplete
  • OnVolumeShadowComplete
  • OnBeforeFolderCreate
  • OnBeforeFileCopy

可用的PascalScript功能

您可以使用以下功能进行呼叫。
  • 标准功能,例如Pos, Copy, Length, Ord
  • function ConcatPath(const a,b:UnicodeString; const t: Int64):UnicodeString;
  • function ConcatPathWithDelim(const a,b,delim:UnicodeString):UnicodeString;
  • function ExtractFileName(const s: UnicodeString):UnicodeString;
  • function ExtractFilePath(const s: UnicodeString):UnicodeString;
  • function ExtractURLPartAfterServer(const s: UnicodeString):UnicodeString;
  • function ExtractFileExt(const s: UnicodeString):UnicodeString;
  • function ChangeFileExt(const s,t: UnicodeString):UnicodeString;
  • function FileExists(const FileName: UnicodeString):Boolean;
  • procedure Log(const s:UnicodeString);
  • procedure MessageBox(const s:UnicodeString);
  • function Execute(const s:UnicodeString; const TimeOutSeconds: Int64):Int64;
  • function GetProfileName:UnicodeString;
  • procedure SetProfileResult(const AResultText:UnicodeString);
  • function ConnFileExists(const Connector:Opaque; const FileName: UnicodeString):Boolean;
  • function ConnCustomFTPCommand(const Connector:Opaque; const ACommand: UnicodeString;const AOkResponse1,AOkResponse2,AOkResponse3:Integer;var ResponseText: UnicodeString):Integer;
  • function ConnRenameFile(const Connector:Opaque; const AFromFileName,AToFileName: UnicodeString):Boolean;
  • function StringReplace(const Source, OldPattern, NewPattern: UnicodeString;const CaseSensitive:Boolean): UnicodeString;
  • function EncodeBase64(const s: UnicodeString):UnicodeString;
  • function DecodeBase64(const s: UnicodeString):UnicodeString;
  • function SimpleEncrypt(const s: UnicodeString):UnicodeString;
  • function SimpleDecrypt(const s: UnicodeString):UnicodeString;
  • function AESEncrypt(const s,passphrase: UnicodeString):UnicodeString;
  • function AESDecrypt(const s,passphrase: UnicodeString):UnicodeString;
  • function ChooseFile(const Prompt,Extension:UnicodeString):UnicodeString;
  • function OpenIniFile(const AFileName:UnicodeString):Int64;
  • procedure CloseIniFile(const AnIni:Int64);
  • function ReadIniString(const AnIni:Int64;const Section,Ident,Default:UnicodeString):UnicodeString;
  • function GetInput(const s: UnicodeString):UnicodeString;
  • function GetPassword(const s: UnicodeString):UnicodeString;
  • function ReadRegistryString(const Key,OptName:UnicodeString):UnicodeString;
  • procedure WriteRegistryString(const Key,OptName,Value:UnicodeString);
  • function GetProfileRunID:UnicodeString;
  • procedure ClearBody;
  • function GetBodyLine(const i:Integer):UnicodeString;
  • procedure SetBodyLine(const i:Integer;const s:UnicodeString);
  • procedure DeleteBodyLine(const i:Integer);
  • procedure AddBodyText(const s:UnicodeString);
  • function GetActionList:UnicodeString;
  • function GetProfileSettings:UnicodeString;
  • function Now:Double;
  • function NowUTC:Double;
  • function OffsetFromUTC:Double;
  • function TimeToStr(const DateTime: Double):UnicodeString;
  • function DateTimeToStr(const DateTime: Double):UnicodeString;
  • function DateToStr(const DateTime: Double):UnicodeString’;
  • function DateTimeToStrWithFormat(const DateTime: Double;const FormatString:UnicodeString):UnicodeString;
  • function MakeSurePathExists(const s:UnicodeString;const isRightSide:Boolean):Boolean;
  • function PathDelim:UnicodeString;
  • function GetDelim(const Connector: Opaque):UnicodeString;
  • function IncludeLeadingPathDelim(const s: UnicodeString):UnicodeString;
  • function OpenTextFile(const s:UnicodeString):Opaque;
  • function CreateTextFile(const s:UnicodeString):Opaque;
  • procedure WriteLine(const F:Opaque;const ALine:UnicodeString);
  • function ReadLine(const F:Opaque):UnicodeString;
  • procedure CloseFile(const F:Opaque);

OnGetCustomHeaders Sample Script

This hook allows you to add custom HTTP headers to Amazon S3 requests. In future Syncovery versions, this feature can be added to other cloud storages and protocols (on customer request – just ask for it).

function OnGetCustomHeaders(const RelativePath: UnicodeString;const
URL:AnsiString;var MIMEType,Headers: AnsiString;const Connector:
Opaque):Boolean;
var strDate:string;
begin
Result:=true;
Headers:='Cache-Control: 10';
Log('');
Log('Headers Added to '+RelativePath);
Log(Headers);
Log('');
end;

OnIncludeItem示例脚本

为同步的每一侧单独调用OnIncludeItem拦截。 isRightSide参数指示我们当前正在查看的那一侧。

以下脚本用于排除没有文件扩展名的文件。这样的排除不可能通过排除掩码实现。

function OnIncludeItem(const FileName, RelativePath: UnicodeString;
const isRightSide, isFolder:Boolean;
const FileSize:Int64; const FileAttr:LongWord;
const Connector: Opaque):Boolean;
begin
Result:=isFolder or (Pos('.',FileName)>0);
end;
OnIncludeItem的第二个示例仅处理包含文件READY.toprocess的子文件夹,以及右侧存在的任何子文件夹。

function OnIncludeItem(const FileName, RelativePath: UnicodeString;
const isRightSide, isFolder:Boolean;
const FileSize:Int64; const FileAttr:LongWord;
const Connector: Opaque):Boolean;
begin
Result:=isRightSide or not isFolder or
ConnFileExists(Connector,ConcatPath(ConcatPath(LeftBasePath,RelativePath,Connector),FileName,Connector)+
'\READY.toprocess');
end;

OnScanFolder示例脚本

这可能是寻找“READY.to process”的更好方法。 在扫描文件夹之前调用OnScanFolder拦截,并且可以在拦截中使用双方的知识。

function OnScanFolder(const FolderLevel: Integer;
const RelativePath, LeftCompletePath, RightCompletePath: UnicodeString;
const LeftExists,RightExists:Boolean;
const LeftConnector, RightConnector: Opaque):Boolean;
begin
Result:=RightExists or ConnFileExists(LeftConnector,LeftCompletePath+'\READY.toprocess');
end;

OnProfileResults示例脚本

此脚本不执行任何操作,但在配置文件完成时使用某些统计信息调用该函数。 可以在此页面顶部附近下载具有一些实际用途的示例(“根据配置文件结果发送电子邮件通知”)。 忽略此函数返回值(“Result”)。

function OnProfileResults(const FilesCopiedL2R,FilesCopiedR2L:Integer;
const FilesToCopyL2R,FilesToCopyR2L:Integer;
const BytesCopiedL2R,BytesCopiedR2L:Int64;
const ResultString:UnicodeString;
const Error:Boolean):Boolean;
begin
Result:=true;
end;

OnReplaceFilenameLeftToRight示例脚本

当文件从左向右复制时,此脚本将重命名文件。 在我们的示例中,在文件扩展名之前添加了“-draft”。

function OnReplaceFilenameLeftToRight(const FileName: UnicodeString;
const isFolder: Boolean):UnicodeString;
begin
if isFolder then
Result:=FileName
else
Result:=ChangeFileExt(FileName,'')+'-draft'+ExtractFileExt(FileName);
end;

OnReplaceFilenameRightToLeft示例脚本

如果您进行双向同步,并且新文件可能出现在右侧,我们还需要一种在另一个方向重命名的方法。 此示例脚本从名称中删除“-draft”插入。

function OnReplaceFilenameRightToLeft(const FileName: UnicodeString;
const isFolder: Boolean):UnicodeString;
var ToFind:UnicodeString;
P:Integer;
begin
if isFolder then
Result:=FileName
else begin
ToFind:=''-draft''+ExtractFileExt(FileName);
p:=Pos(ToFind,FileName);
if p>0 then
Result:=Copy(FileName,1,p-1)+ExtractFileExt(FileName)
else
Result:=FileName
end;
end;

OnUploadComplete示例脚本

此脚本将为通过FTP上传到777的文件设置权限。

function OnUploadComplete(const FileName, LocalFilePath, CompleteURL: UnicodeString;
const isRightSide:Boolean;
const FileSize:Int64;
const Connector: Opaque):Boolean;
var CmdRes:Int64;
ResponseText:UnicodeString;
begin
CmdRes:=ConnCustomFTPCommand(Connector,'SITE CHMOD 777 '+FileName,200,200,200,ResponseText);
Log('Set Permissions for '+FileName+': '+ResponseText);
Result:=true;
end;

OnDownloadComplete示例脚本

此脚本将通过添加额外的“.downloaded”扩展名来重命名下载的文件。

function OnDownloadComplete(const FileName, CompleteURL, LocalFilePath: UnicodeString;
const isRightSide:Boolean;
const FileSize:Int64;
const Connector: Opaque):Boolean;
begin
if ConnRenameFile(Connector,CompleteURL,FileName+'.downloaded') then
Log('Renamed '+FileName+' to '+FileName+'.downloaded')
else
Log('Rename failed: '+FileName+' to '+FileName+'.downloaded');
Result:=true;
end;

OnVolumeShadowComplete示例脚本

在创建卷影后,此脚本将执行外部命令(批处理或CMD文件)。

function OnVolumeShadowComplete(const Volume,ShadowPath:UnicodeString):Boolean;
begin
Result:=Execute('C:\Tests\test.bat',120)=0;
end;

OnBeforeFolderCreate示例脚本

此脚本将阻止创建任何文件夹,除非有必要将文件复制到目标文件夹。 您还可以使用此拦截来操作目标上的文件夹路径。

function OnBeforeFolderCreate(const DirectionIsL2R:Boolean;
var Source,Dest,Reason:UnicodeString):Boolean;
begin
Result:=false;
end;

OnBeforeFileCopy示例脚本

该脚本将通过添加源端不存在的附加子文件夹“archive”来操作复制的目标路径(从左到右)。

function OnBeforeFileCopy(const DirectionIsL2R:Boolean;
var Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString):Boolean;
var AddFolderName,NewDestPath,NewDest,NewRightSubPath:UnicodeString;
begin
Result:=true;
if not DirectionIsL2R then
Exit;
AddFolderName:='archive'
NewDestPath:=ConcatPathWithDelim(DestPath,AddFolderName,PathDelim);
NewDest:=ConcatPathWithDelim(NewDestPath,ExtractFileName(Dest),PathDelim);
NewRightSubPath:=IncludeLeadingPathDelim(ConcatPathWithDelim(RightSubPath,AddFolderName,PathDelim));

if not MakeSurePathExists(NewDestPath,true) then begin
Log('Could not create '+NewDestPath);
Exit;
end;

Log('OnBeforeFileCopy');
Log('Source:'+Source);
Log('DestPath:'+DestPath+' changed to '+NewDestPath);
Log('Dest:'+Dest+' changed to '+NewDest);
Log('LeftSubPath:'+LeftSubPath);
Log('RightSubPath:'+RightSubPath+' changed to '+NewRightSubPath);
Log('');

Dest:=NewDest;
DestPath:=NewDestPath;
RightSubPath:=NewRightSubPath;
end;

OnGetProfilePathBeforeListing示例脚本

此脚本使用此拦截为配置文件指定单独的TEMP文件夹。 该功能的最初目的是修改左或右路径和/或凭证。

function OnGetProfilePathBeforeListing(const isRightSide:Boolean;
var Path,UserName,Password:UnicodeString;
var AuthKey,AuthKeyPassword:AnsiString;
var Port:Integer):Boolean;
begin
ProfileTempDir:='H:\TEMP';
Result:=true;
end;